package com.lingx.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.PrivateKey;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.lingx.bean.CascaderBean;
import com.lingx.bean.ContextBean;
import com.lingx.bean.TokenBean;
import com.lingx.bean.UserBean;
import com.lingx.model.Constants;
import com.lingx.model.IContext;
import com.lingx.model.IExecutor;
import com.lingx.model.IInterpreter;
import com.lingx.model.IModel;
import com.lingx.model.INode;
import com.lingx.model.IValidator;
import com.lingx.model.annotation.FieldModelConfig;
import com.lingx.model.annotation.TreeNode;
import com.lingx.model.impl.DefaultConfig;
import com.lingx.model.impl.DefaultEntity;
import com.lingx.model.impl.DefaultField;
import com.lingx.model.impl.DefaultMethod;
import com.lingx.model.impl.ExpressionExecutor;
import com.lingx.model.impl.tools.ModelIO;
import com.lingx.model.impl.tools.ModelTemplate;
import com.lingx.utils.AnnoUtils;
import com.lingx.utils.TokenUtils;
import com.lingx.utils.Utils;
import com.lingx.web.api.IApi;
import com.lingx.web.local.rsa.SecurityRsa;

@Component("lingxModelService")
public class ModelService {
	public static Map<String,DefaultEntity> ENTITY_CACHE = Collections .synchronizedMap(new HashMap<>());
	@Resource
	private JdbcTemplate jdbcTemplate;
	@Resource
	private List<IValidator> validators;
	@Resource
	private List<IInterpreter> interpreters;
	@Resource
	private MethodService methodService;
	@Resource 
	private InterpretService interpretService;
	@Resource 
	private DefaultValueService defaultValueService;
	@Resource
	private UserService userService;
	public String getStringByList(List<String> list){
		StringBuilder sb=new StringBuilder();
		for(String str:list){
			sb.append(str).append(",");
		}
		if(sb.length()>0)sb.deleteCharAt(sb.length()-1);
		return sb.toString();
	}
	public IValidator getValidator(String type) {
		IValidator obj=null;
		for(IValidator o:this.validators) {
			if(type.equals(o.getType())) {
				obj=o;break;
			}
		}
		return obj;
	}
	public IInterpreter getInterpreter(String type) {
		IInterpreter obj=null;
		for(IInterpreter o:this.interpreters) {
			if(type.equals(o.getType())) {
				obj=o;
				break;
			}
		}
		return obj;
	}
	public DefaultEntity getDefaultEntity() {
		return new DefaultEntity();
	}
	public  Map<String,DefaultEntity> getEntityCache() {
		return ENTITY_CACHE;
	}
	public String decode(String key1,String key2) {
		try {
			PrivateKey privateKey=SecurityRsa.getPrivateKey(key2);
			return SecurityRsa.decrypt(key1, privateKey);
		} catch (Exception e) {
			return "";
		}
	}
	public List<Map<String, Object>> getTreeList(DefaultEntity entity,String id) {
		IModel model=this.getById(entity, id);
		List<Object> list=AnnoUtils.getField(model.getClass(), TreeNode.class, model);
		List<Map<String,Object>> nodes=new ArrayList<Map<String,Object>>();
		for(Object obj:list){
			if(obj instanceof IModel){
				Map<String,Object> map=new HashMap<String,Object>();
				IModel m=(IModel)obj;
				map.put("id",m.getId() );
				map.put("modelType",m.getModelType() );
				if(m.getModelType().equals("Node")) {
				//if(m.getName().equals("配置")|| m.getName().equals("属性")||m.getName().equals("操作")||m.getName().equals("验证器")||m.getName().equals("解释器")||m.getName().equals("执行器")||m.getName().equals("表达式执行器")||m.getName().equals("脚本代码")){
					map.put("label",m.getName() );
				}else{
					map.put("label",m.getName()+" ["+m.getCode()+"]" );
				}
				map.put("code", m.getCode());
				map.put("name", m.getName());
				map.put("icon",m.getIconCls());
				map.put("leaf", m.getLeaf());
				if(obj instanceof INode){
					map.put("expanded", true);
				}
				nodes.add(map);
			}else if(obj instanceof List){
				List<IModel> ll=(List<IModel>)obj;
				for(IModel m:ll){
					Map<String,Object> map=new HashMap<String,Object>();
					map.put("id",m.getId() );
					map.put("modelType",m.getModelType() );
					if(m.getModelType().equals("Node")) {
					//if(m.getName().equals("配置")|| m.getName().equals("属性")||m.getName().equals("操作")||m.getName().equals("验证器")||m.getName().equals("解释器")||m.getName().equals("执行器")||m.getName().equals("表达式执行器")||m.getName().equals("脚本代码")){
						map.put("label",m.getName());
					}else{
						map.put("label",m.getName()+" ["+m.getCode()+"]" );
					}
					map.put("code", m.getCode());
					map.put("name", m.getName());
					map.put("icon",m.getIconCls());
					map.put("leaf", m.getLeaf());
					nodes.add(map);
				}
			}else{
			}
		}
		return nodes;
	}
	
	public DefaultEntity createDefaultModel(String table,String name,String author,int idtype,String dbName){
		return ModelTemplate.createEntity(table, name, author, idtype, dbName,jdbcTemplate);
	}
	
	public void save(DefaultEntity entity){
		try {
			ENTITY_CACHE.put(entity.getCode(), entity);
			ModelIO.writeEntity(entity, jdbcTemplate);
		} catch (Exception e) {
			//e.printStackTrace();
		}
	}
	
	public IModel clone(IModel model){
		return (IModel)ModelIO.clone(model);
	}

	public IModel getById(IModel entity, String id) {
		IModel model=null;
		if(entity==null){return null;}
		//Field fields[]=entity.getClass().getDeclaredFields();
		Field[] fields1=entity.getClass().getDeclaredFields();
		Field[] fields2=entity.getClass().getSuperclass().getDeclaredFields();
		Field[] fields=new Field[fields1.length+fields2.length];
		System.arraycopy(fields1, 0, fields, 0, fields1.length);
		System.arraycopy(fields2, 0, fields, fields1.length, fields2.length);
		if(id.equals(entity.getId())){return entity;}
		for(Field field:fields){
			try {
				field.setAccessible(true); 
				Object o=field.get(entity);
				if(o instanceof IModel){
					IModel m=(IModel)o;
					if(id.equals(m.getId())){
						model= m;
						if(model!=null)return model;
					}else{
						model= getById(m,id);
						if(model!=null)return model;
					}
				}else if(o instanceof List){
					List<IModel> ll=(List<IModel>)o;
					for(IModel m:ll){
						if(id.equals(m.getId())){
							model= m;
							if(model!=null)return model;
						}else{
							model= getById(m,id);
							if(model!=null)return model;
						}
					}
				}else{
					//System.out.println("--getById--未处理--"+field.getName());
				}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return model;
	}
	public DefaultEntity getEntityByCache(String code) {
		if(ENTITY_CACHE.containsKey(code)) {
			return ENTITY_CACHE.get(code);
		}else {
			return this.getEntity(code);
		}
	}
	public DefaultEntity getEntity(String code) {
		try {
			DefaultEntity temp=ModelIO.readEntity(code, jdbcTemplate);
			ENTITY_CACHE.put(code, temp);
			return temp;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public boolean saveProperty(String code, String id, String prop,
			String value, String oldvalue, String author) {

		DefaultEntity entity=getEntity(code);
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String time=sdf.format(new Date());
		try {
			IModel ae= getById(entity, id);
			prop=getPropertyNameFor_(prop);
			invokeSet(ae,prop,value);
			fieldSynchro(entity,ae,prop,value);
			ae.setAuthor(author);
			ae.setLastModifyTime(time);
			save(entity);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public String addModel(DefaultEntity entity,String id ,IModel model){
		IModel m=this.getById(entity, id);
		if(m instanceof INode){
			INode n=(INode)m;
			n.getList().add(model);
			save(entity);
			return model.getId();
		}else{
			//System.out.println(m.getClass().getName());
			return null;
		}
	}

	public Map<String, Object> getBySort(Object o) {

		Map<String,Object> map=new HashMap<String,Object>();
		if(o==null)return map;
		java.lang.reflect.Method[] methods=o.getClass().getMethods();
		for(java.lang.reflect.Method m:methods){
			String name=m.getName();
			if(name.indexOf("get")==0){
				try {
					Object value=m.invoke(o);
					if(value==null)value="";
					if(value instanceof List)continue;
					if(value instanceof Class)continue;
						java.lang.reflect.Field f=null;
						try {
							f=o.getClass().getDeclaredField(getDojoFieldByMethodName(name));
						} catch (Exception e1) {
							f=o.getClass().getSuperclass().getDeclaredField(getDojoFieldByMethodName(name));
						}
						FieldModelConfig anno=f.getAnnotation(FieldModelConfig.class);
						
						if(anno!=null){
							if("hidden".equals(anno.editor()))continue;
							map.put(anno.sort()+"_"+getDojoFieldByMethodName(name), value);
						}else{
							map.put(getDojoFieldByMethodName(name), value);
						}
				} catch (Exception e1) {
					//e1.printStackTrace();
				} 
			}
		}
		return map;
	}

	public Map<String, Object> getByAnno(Object o) {

		Map<String,Object> map=new HashMap<String,Object>();
		if(o==null)return map;
		java.lang.reflect.Method[] methods=o.getClass().getMethods();
		for(java.lang.reflect.Method m:methods){
			String name=m.getName();
			if(name.indexOf("get")==0){
				try {
					Object value=m.invoke(o);
					if(value instanceof List)continue;
					if(value instanceof Class)continue;
					Map<String,Object> prop=new HashMap<String,Object>();
					
						java.lang.reflect.Field f=null;
						try {
							f=o.getClass().getDeclaredField(getDojoFieldByMethodName(name));
						} catch (Exception e1) {
							f=o.getClass().getSuperclass().getDeclaredField(getDojoFieldByMethodName(name));
						}
						FieldModelConfig anno=f.getAnnotation(FieldModelConfig.class);
						if(anno!=null){
							map.put(anno.sort()+"_"+getDojoFieldByMethodName(name), prop);
							prop.put("displayName", anno.name());
							if( anno.editor()!=null&&!"".equals(anno.editor())){
								prop.put("editor", anno.editor());
							}else {
								prop.put("editor", "text");
							}
						}else{
							map.put(getDojoFieldByMethodName(name), prop);
						}
				} catch (Exception e1) {
					//e1.printStackTrace();
				} 
			}
		}
		return map;
	}

	public static <T> T[] concatAll(T[] first, T[]... rest) {
		  int totalLength = first.length;
		  for (T[] array : rest) {
		    totalLength += array.length;
		  }
		  T[] result = Arrays.copyOf(first, totalLength);
		  int offset = first.length;
		  for (T[] array : rest) {
		    System.arraycopy(array, 0, result, offset, array.length);
		    offset += array.length;
		  }
		  return result;
		}
	public List<Map<String, Object>> getByAnnoList(Object o) {
		List<Map<String, Object>> list=new ArrayList<>();
		if(o==null)return list;
		java.lang.reflect.Method[] methods=o.getClass().getMethods();
		for(java.lang.reflect.Method m:methods){
			String name=m.getName();
			if(name.indexOf("get")==0){
				try {
					Object value=m.invoke(o);
					if(value instanceof List)continue;
					if(value instanceof Class)continue;
					Map<String,Object> prop=new HashMap<String,Object>();
					
						java.lang.reflect.Field f=null;
						try {
							f=o.getClass().getDeclaredField(getDojoFieldByMethodName(name));
						} catch (Exception e1) {
							f=o.getClass().getSuperclass().getDeclaredField(getDojoFieldByMethodName(name));
						}
						FieldModelConfig anno=f.getAnnotation(FieldModelConfig.class);
						if(anno!=null){
							//map.put(anno.sort()+"_"+getDojoFieldByMethodName(name), prop);
							prop.put("id", getDojoFieldByMethodName(name));
							prop.put("name", anno.name());
							prop.put("value", value);
							prop.put("isEdit", false);
							prop.put("sort", anno.sort());
							String editor=anno.editor();
							if("hidden".equals(editor))continue;
							if(editor!=null&&!"".equals(editor)){
								prop.put("editor", editor);
							}else {
								prop.put("editor", "text");
							}
							
							prop.put("items", new String[] {});

							String editorParams=anno.editorParams();
							
							if(Utils.isNull(editorParams)) {
								
							}else if("editorParams_1".equals(editorParams)) {
								 List<Map<String,Object>> items=this.jdbcTemplate.queryForList("select id ,code value,name text from tlingx_entity where is_ref='1' order by create_time desc");
								 prop.put("items", items);
							}else if("editorParams_2".equals(editorParams)) {
								 List<Map<String,Object>> items=new ArrayList<>();
								 for(IValidator obj:this.validators) {
									 Map<String,Object> m1=new HashMap<>();
									 m1.put("text", obj.getName());
									 m1.put("value", obj.getType());
									 m1.put("id", obj.getId());
									 items.add(m1);
								 }
								 prop.put("items", items);
							}else if("editorParams_3".equals(editorParams)) {
								List<Map<String,Object>> items=new ArrayList<>();
								 for(IInterpreter obj:this.interpreters) {
									 Map<String,Object> m1=new HashMap<>();
									 m1.put("text", obj.getName());
									 m1.put("value", obj.getType());
									 m1.put("id", obj.getId());
									 items.add(m1);
								 }
								 prop.put("items", items);
							}else if(editorParams.startsWith("option:")) {
								 List<Map<String,Object>> items=this.jdbcTemplate.queryForList("select name text,value from tlingx_optionitem where enabled=1 and option_id in (select id from tlingx_option where code=?) order by orderindex asc ",editorParams.split(":")[1]);
								 prop.put("items", items);
							}
							/*
							if( anno.editor()!=null&&!"".equals(anno.editor())){
								if("text".equals(anno.editor())||"hidden".equals(anno.editor())||"text".equals(anno.editor()))continue;
									if(anno.editor().indexOf("new ")>-1){
										prop.put("editor", anno.editor());
									}
							}*/
							list.add(prop);
						}
				} catch (Exception e1) {
					//e1.printStackTrace();
				} 
			}
		}
		return list;
	}

	public Map<String, Object> getProperty(String code, String id) {
		DefaultEntity entity=getEntity(code);
		IModel o=getById(entity, id);
		Map<String,Object> map=new HashMap<String,Object>();
		map.put("prop", getBySort(o));
		map.put("propAnno", getByAnno(o));
		return map;
	}
	public String getDojoFieldByMethodName(String methodName) {
		String temp=methodName.substring(4);
		String a3=String.valueOf(methodName.charAt(3));
		return a3.toLowerCase()+temp;
	}
	private  void invokeSet(Object obj,String field,String value)throws Exception{
		java.lang.reflect.Method[] methods=obj.getClass().getMethods();
		
		for(java.lang.reflect.Method m:methods){
			String name=m.getName();
			if(name.indexOf("set")==0){
				Class c[] = m.getParameterTypes();
				Class clazz= c[0];
				if(clazz.isInterface())continue;
				if(getDojoFieldByMethodName(name).equals(field)){
					initObjectParam(clazz,m,obj,value);
				}
			}
		}
	}
	public String getPropertyNameFor_(String name) {
		return name.substring(name.indexOf('_')+1);
	}
	private  void initObjectParam(Class clazz, java.lang.reflect.Method m,
			Object exeObject,String value) {
		
		String param=value;
		try {
			if (clazz.equals(String.class)) {
				if (Utils.isNull(param))
					param = "";
				m.invoke(exeObject, param);
			} else if (clazz.equals(Integer.class)) {
				if (Utils.isNull(param))
					param = "0";
				m.invoke(exeObject, Integer.parseInt(param));
			} else if (clazz.equals(Long.class)) {
				if (Utils.isNull(param))
					param = "0";
				m.invoke(exeObject, Long.parseLong(param));
			} else if (clazz.equals(Float.class)) {
				if (Utils.isNull(param))
					param = "0";
				m.invoke(exeObject, Float.parseFloat(param));
			} else if (clazz.equals(Double.class)) {
				if (Utils.isNull(param))
					param = "0";
				m.invoke(exeObject, Double.parseDouble(param));
			} else if (clazz.equals(Boolean.class)) {
				if (Utils.isNull(param))
					param = "false";
				m.invoke(exeObject, "true".equals(param));
			} else {
				System.out.println("找不到:"+clazz.toString());
				m.invoke(exeObject, "true".equals(param));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private  void fieldSynchro(DefaultEntity entity,IModel f,String prop,String value){
		if(f instanceof DefaultField){
			DefaultField field=(DefaultField)f;
			if(field.getFieldSynchro()){
				for(DefaultField temp:entity.getFields().getList()){
					if(temp==field)continue;
					if(temp.getCode().equals(field.getCode())&&temp.getFieldSynchro()){
						try {
							invokeSet(temp,prop,value);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
				for(DefaultMethod method:entity.getMethods().getList()){
					for(DefaultField temp:method.getFields().getList()){
						if(temp==field)continue;
						if(temp.getCode().equals(field.getCode())&&temp.getFieldSynchro()){
							try {
								invokeSet(temp,prop,value);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}
				}
			}
		}
	}

	
	private void add(List<DefaultField> list,String code,String order){
		int index=0;
		for(DefaultField field:list ){
			index++;
			if(field.getCode().equals(order)){
				break;
			}
		}
		DefaultField field=new DefaultField();
		field.setCode(code);
		field.setName(code);
		list.add(index, field);
	}
	public DefaultField addField(String code, String id) {
		DefaultField f=new DefaultField();
		 this.addModel(getEntity(code), id,f );
		return f;
	}

	public DefaultMethod addMethod(String code, String id) {
		DefaultMethod m=new DefaultMethod();
		m.setValidation(true);
		m.setCurrentRow(true);
		m.setFields(ModelTemplate.getFieldNode(new ArrayList<>()));
		List<IExecutor> exeList1=new ArrayList<IExecutor>();
		ExpressionExecutor ce1=new ExpressionExecutor();
		exeList1.add(ce1);
		m.setExecutors(ModelTemplate.getExecutorNode(exeList1));
		this.addModel(getEntity(code), id, m);
		return m;
	}


	public String addExecutor(String code, String id) {
		return this.addModel(getEntity(code), id, new ExpressionExecutor());
	}

	private void removeForeach(Object source,Object target){
		List<Object> list=AnnoUtils.getField(source.getClass(), TreeNode.class, source);
		for(Object obj:list){
			if(obj instanceof INode){
				INode node=(INode)obj;
				if(node.getList().contains(target)){
					node.getList().remove(target);
					break;
				}else{
					for(Object o:node.getList()){
						removeForeach(o,target);
					}
				}
			}
		}
	}
	public boolean remove(String code, String ids) {
		DefaultEntity entity=getEntity(code);
		String array[]=ids.split(",");
		for(String id:array){
			IModel model=this.getById(entity, id);
			removeForeach(entity,model);
		}
		save(entity);
		return true;
	}

	public List<IValidator> getValidators() {
		return validators;
	}

	public List<IInterpreter> getInterpreters() {
		return interpreters;
	}

	public Map<String,Object> getEditParams(DefaultEntity entity,String mcode,String eid,Map<String, Object> params){
		Map<String,Object> ret=IApi.getRetMap();
		DefaultMethod method=this.methodService.getMethod(mcode, entity);
		TokenBean token=TokenUtils.getTokenData(params.get("lingxtoken").toString());
		UserBean userBean =new UserBean();
		userBean.setId(token.getUserId());
		userBean.setOrgId(token.getOrgId());
		IContext context = new ContextBean(userBean,entity,method);;
		List<DefaultField> fields=null;
		if(this.methodService.defaultMethodContains(mcode)) {
			fields=entity.getFields().getList();
		}else {
			fields=method.getFields().getList();
		}
		
		for(DefaultField field:fields) {
			if("tlingx_optionitem".equals(field.getRefEntity())) {
				 List<Map<String,Object>> items=this.jdbcTemplate.queryForList("select name text,value from tlingx_optionitem where enabled=1 and option_id in (select id from tlingx_option where code=?) order by orderindex asc ",field.getInputOptions());
				 field.setOptionitem(items);
			}
		}
		this.setValueForDefaultValue(fields, context, params);
		this.setValueForRequest(fields, params);
		//System.out.println(JSON.toJSONString(fields));
		if(Utils.isNotNull(eid)&&method.getCurrentRow()) {
			Map<String,Object> record=this.jdbcTemplate.queryForMap("select * from "+entity.getTableName()+" where id=?",eid);
			this.interpretService.outputFormat(record, fields, entity);
			for(DefaultField field:fields) {
				if(record.containsKey(field.getCode()))
				field.setValue(record.get(field.getCode()));
			}
		}else {
			Map<String,Object> map=new HashMap<>();
			for(DefaultField field:fields) {
				if(field.getValue()!=null) {
					map.put(field.getCode(), field.getValue());
				}
			}
			//System.out.println(JSON.toJSONString(map));
			this.interpretService.outputFormat(map, fields, entity);
			for(DefaultField field:fields) {
				field.setValue(map.get(field.getCode()));
			}
		}
		Map<String,Object> methodOption=new HashMap<>();

		methodOption.put("code", method.getCode());
		methodOption.put("name", method.getName());
		methodOption.put("readonly", method.getReadonly());
		methodOption.put("prompt", method.getPrompt());
		methodOption.put("confirm", method.getConfirm());
		ret.put("fields", fields);
		ret.put("method", methodOption);
		return ret;
	}
	public  Map<String,Object> getGridParams(DefaultEntity entity,Map<String,Object> requestParams){
		Map<String,Object> params=new HashMap<String,Object>();
		
		List<Map<String,Object>> columns=new ArrayList<Map<String,Object>>();
		List<Map<String,Object>> toolbar=new ArrayList<Map<String,Object>>();
		for(DefaultField field:entity.getFields().getList()){
			if(!field.getVisible())continue;
			
			Map<String,Object> c=new HashMap<String,Object>();
			c.put("header",field.getName());
			c.put("dataIndex", field.getCode());
			c.put("visible", field.getVisible());
			if(Utils.isNotNull(field.getWidth())){
				try{
				c.put("width", Integer.parseInt(field.getWidth()));
				}catch(Exception e){}
			}else {
				c.put("width", 150);
			}
			c.put("dataType", "text");
			if(field.getRefEntity()!=null&&!"".equals(field.getRefEntity())&&field.getEscape()&&field.getIsEntityLink()){//tlingx_optionitem_NO 这里本来的处理，是为了字典在界面上不能点击，但会导致，需要该字段字时，会取不到，所以取消
				c.put("dataType", "object");
				/*
				if(field.getIsEntityLink()&&!"tlingx_optionitem".equals(field.getRefEntity())){
					DefaultEntity refEntity=getEntity(field.getRefEntity());
					c.put("formatter", new Function("function(record, column, value, index){	var temp='';	if(!value)return temp; if(value."+field.getCode()+")value=value."+field.getCode()+";	for(var i=0;i<value.length;i++){		temp=temp+'<a href=\"javascript:;\" onclick=\"openViewWindow(\\'"+refEntity.getCode()+"\\',\\'"+refEntity.getName()+"\\',\\''+value[i].id+'\\');\">'+value[i].text+'</a>,';	}	temp=temp.substring(0,temp.length-1); 	return temp;}"));
				
				}else{
					c.put("formatter", new Function("function(record, column, value, index){	var temp='';	if(!value)return temp; if(value."+field.getCode()+")value=value."+field.getCode()+";	for(var i=0;i<value.length;i++){		temp=temp+value[i].text+',';	}	temp=temp.substring(0,temp.length-1); 	return temp;}"));
				}*/
			}
			if("file".equals(field.getInputType())){
				c.put("dataType", "file");
				//c.put("formatter", new Function("function(record, column, value, index){	if(!value)return ''; if(value."+field.getCode()+")value=value."+field.getCode()+";  var temp=value; var fvalue=''; if(temp&&temp.length>1&&temp.charAt(0)=='['){ var tempText=\"\"; var tempArr=Lingx.parseJSON(temp); for(var ii=0;ii<tempArr.length;ii++){ tempText+=\"<a target='_blank' href='\"+tempArr[ii].value+\"' >\"+tempArr[ii].text+\"</a>,\"; } if(tempText.length>0){ tempText=tempText.substring(0,tempText.length-1); } fvalue=tempText; }else{ fvalue=\"<a target='_blank' href='\"+value+\"' >"+"下载"+"</a>\"; }return fvalue;}"));
			}
			if("image".equals(field.getInputType())){
				c.put("dataType", "image");
				//c.put("formatter", new Function("function(record, column, value, index){	if(!value)return ''; if(value."+field.getCode()+")value=value."+field.getCode()+";  var temp=value; var fvalue=''; if(temp&&temp.length>1&&temp.charAt(0)=='['){ var tempText=\"\"; var tempArr=Lingx.parseJSON(temp); for(var ii=0;ii<tempArr.length;ii++){ tempText+=\"<a target='_blank' href='\"+tempArr[ii].value+\"' ><img height=\'60\' src='\"+tempArr[ii].value+\"' /></a>,\"; } if(tempText.length>0){ tempText=tempText.substring(0,tempText.length-1); } fvalue=tempText; }else{ fvalue=\"<a target='_blank' href='\"+value+\"' ><img height=\'60\' src='\"+value+\"' /></a>\"; }return fvalue;}"));
				
			}
			
			columns.add(c);
		}
		List<DefaultMethod> methodList=new ArrayList<DefaultMethod>();
		methodList.addAll(entity.getMethods().getList());
		methodList.addAll(this.methodService.getDefaultMethods());
		String token=IApi.getParamString(requestParams, "lingxtoken", "");
		String userid=TokenUtils.getTokenDataUserId(token);
		for(DefaultMethod method:methodList){
			if(!this.userService.isAuthFunc(userid, entity.getCode(), method.getCode()))continue;
			if(method.getVisible()||method.getOperateRow()||method.getRightmenu()){
				Map<String,Object> m=new HashMap<String,Object>();
				m.put("xtype", "button");
				m.put("text",method.getName());
				m.put("iconCls",method.getIconCls());
				m.put("code", method.getCode());
				m.put("name",method.getName());
				m.put("buttonType", method.getButtonType());
				m.put("operateRow", method.getOperateRow());
				m.put("currentRow", method.getCurrentRow());
				m.put("disabled", !method.getEnabled()); //disabled
				m.put("viewUri", method.getViewUri());
				m.put("visible", method.getVisible());
				m.put("rightmenu", method.getRightmenu());
				//m.put("handler",new Function("function(){methodWindow(this,"+JSON.toJSONString(entity, SerializerFeature.DisableCircularReferenceDetect)+","+JSON.toJSONString(method, SerializerFeature.DisableCircularReferenceDetect)+")}"));
				toolbar.add(m);
			}
			
			
		}
		params.put("GridConfig", entity.getConfigs().getList().get(0));
		params.put("columns",columns);
		params.put("toolbar",toolbar);
		
		//params.put("fields", entity.getFields());//
		params.put("code", entity.getCode());
		params.put("name", entity.getName());
		params.put("textField", this.getTextField(entity));
		params.put("cascades", this.getCascaderList( entity));
		params.put("queryFields", new int[] {});
		
		if(Utils.isNotNull(entity.getConfigs().getList().get(0).getQueryField())) {
			String json=entity.getConfigs().getList().get(0).getQueryField();
			if(json.charAt(0)=='[') {
				List<Map<String,Object>> list=(List<Map<String,Object>>)JSON.parse(json);
				for(Map<String,Object> map:list) {
					if("combobox".equals(map.get("editor").toString())&&map.containsKey("optioncode")) {
						String optioncode=map.get("optioncode").toString();
						List<Map<String,Object>> items=this.jdbcTemplate.queryForList("select name text,value from tlingx_optionitem where enabled=1 and option_id in (select id from tlingx_option where code=?) order by orderindex asc ",optioncode);
						map.put("optionitem", items);
					}
					map.remove("where");//显示不展示这个属性
				}

				params.put("queryFields", list);
			}
		}
		return params;
	}

	public DefaultField getFieldByEntity(DefaultEntity entity,DefaultEntity refEntity){
		return getFieldByEntity(entity,refEntity.getCode());
	}
	/**
	 * 取出entity指向refEntity的字段
	 * @param entity
	 * @param refEntity
	 * @return
	 */
	public DefaultField getFieldByEntity(DefaultEntity entity,String refEntityCode){
		DefaultField field=null;
		for(DefaultField f:entity.getFields().getList()){
			if(f.getRefEntity()!=null&&f.getRefEntity().equals(refEntityCode)){
				field=f;break;
			}
		}
		return field;
	}
	public List<String> getParamField(DefaultEntity scriptEntity){
		List<DefaultField> fs=scriptEntity.getFields().getList();
		List<String> list=new ArrayList<String>();
		String temp=Constants.REF_DEFAULT;
		if(fs!=null)
		for(DefaultField f:fs){
			if(Constants.REF_PARAM.equals(f.getComboType())){
				temp=f.getCode();
				list.add(temp);
			}
		}
		
		return list;
	}
	public List<String> getTextField(DefaultEntity scriptEntity){
		List<DefaultField> fs=scriptEntity.getFields().getList();
		List<String> list=new ArrayList<String>();
		String temp=Constants.REF_DEFAULT;
		if(fs!=null)
		for(DefaultField f:fs){
			if(Constants.REF_DISPLAY.equals(f.getComboType())){
				temp=f.getCode();
				list.add(temp);
			}
		}
		if(list.size()==0)
		{
			list.add(temp);
		}		
		return list;
	}
	public String getValueField(DefaultEntity scriptEntity){
		List<DefaultField> fs=scriptEntity.getFields().getList();
		String temp=Constants.REF_DEFAULT;
		if(fs!=null)
		for(DefaultField f:fs){
			if(Constants.REF_VALUE.equals(f.getComboType())){
				temp=f.getCode();
				break;
			}
		}
		return temp;
	}

	public List<Map<String, Object>> getCascaderList(DefaultEntity entity){
		String text=entity.getConfigs().getList().get(0).getCascade();
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		if(text==null||"".equals(text))return list;
		if(text.charAt(0)=='['){
			List<CascaderBean> configs=JSON.parseArray(text,CascaderBean.class);
			for(CascaderBean config:configs){
				String code=config.getEntity();
				DefaultEntity se =this.getEntity(code);
				if (se != null && se.getFields() != null) {
				
					String refField = "";
					for (DefaultField f : se.getFields().getList()) {
						if (this.getEntity(f.getRefEntity())!=null&&entity.getTableName().equals(this.getEntity(f.getRefEntity()).getTableName())) {
							refField = f.getCode();
							break;
						}
					}
					
						Map<String, Object> map = new HashMap<String, Object>();
						map.put("entity", code);
						map.put("name", config.getName()!=null?config.getName():se.getName());
						map.put("refField", refField);
						map.put("method", config.getMethod()!=null?config.getMethod():"grid");
						map.put("where",config.getWhere()!=null?config.getWhere():"{}");
						
						Map<String,Object> map2=new HashMap<>();
						map2.put("_refEntity_", entity.getCode());
						map2.put("_refId_", refField);
						map2.put("rule",config.getRule()!=null?config.getRule():"");
						map2.put(refField, "lingxwait");
						map.put("queryFilter", map2);
						list.add(map);
					
				}
			}
			
		}else{
			String codes[] = text.split(",");
			for (String code : codes) {
				DefaultEntity se =this.getEntity(code);
				if (se != null && se.getFields() != null) {
					boolean b1 = false;
					String refField = "";
					for (DefaultField f : se.getFields().getList()) {
						if (this.getEntity(f.getRefEntity())!=null&&entity.getTableName().equals(this.getEntity(f.getRefEntity()).getTableName())) {
							b1 = true;
							refField = f.getCode();
							break;
						}
					}
					if (b1) {
						//b = true;
						Map<String, Object> map = new HashMap<String, Object>();
						map.put("entity", code);
						map.put("name", se.getName());
						map.put("refField", refField);
						map.put("method", "grid");
						map.put("rule", "");
						map.put("where","{}");
						map.put("queryFilter", new Object());
						list.add(map);
					}
				}
			}
		}
		return list;
	}
	

	public  void setValueForDefaultValue(List<DefaultField> listFields,IContext context,Map<String,Object> params){
		String temp;
		for(DefaultField field:listFields){
			temp=field.getDefaultValue();
			if(Utils.isNotNull(temp)&&temp.indexOf("$")>=0){
				temp=this.defaultValueService.transform(temp,params,context);
				field.setValue(temp);
			}else {
				field.setValue(temp);
			}
		}
	}
	public  void setValueForRequest(List<DefaultField> listFields,Map<String,Object> params){
		String temp="", target="";
		for(DefaultField field:listFields){
			if(params.containsKey(field.getCode()))field.setValue(params.get(field.getCode()));
			
			temp=field.getDefaultValue();
			if(Utils.isNotNull(temp)&&temp.indexOf("$")>=0) {
				//System.out.println("默认值:"+temp);
			for(String key:params.keySet()){
				if( params.get(key)!=null&&!"".equals(params.get(key).toString())){
					target=temp.replace("${param."+key+"}", params.get(key).toString());
					//System.out.println("转换值:"+target);
					if(!temp.equals(target)){//转换成功再赋值，不然会覆盖之前的有效值
					field.setValue(target);

					//System.out.println("设置值:"+target);
					break;
					}
				}
			}}
		}
		
		
		/*
		 * 根据外关键从数据库里取值
		 */
		//System.out.println("_refEntity_:"+_refEntity_);
		if(params.containsKey("_refEntity_")){
			String _refEntity_=IApi.getParamString(params, "_refEntity_", "");//request.getParameter("_refEntity_");
			String _refId_=IApi.getParamString(params, "_refId_", "");//request.getParameter("_refId_");
			DefaultEntity entity=this.getEntity(_refEntity_);
			String code=null;
			for(DefaultField field :listFields){
				if(_refEntity_.equals(field.getRefEntity())){
					code=field.getCode();
					break;
				}
			}

			//System.out.println("code:"+code);
			if(code!=null){
				try {
					String sqlCount="select count(*) from "+entity.getTableName()+" where "+this.getValueField(entity)+"=?";
					
					String sql="select * from "+entity.getTableName()+" where "+this.getValueField(entity)+"=?";
					if(this.jdbcTemplate.queryForObject(sqlCount, Integer.class,_refId_!=null?_refId_:params.get(code))>0) {
						Map<String,Object> map=this.jdbcTemplate.queryForMap(sql,_refId_!=null?_refId_:params.get(code));
						for(DefaultField field:listFields){
							if(Utils.isNotNull(field.getDefaultValue())){
								temp=field.getDefaultValue();
								if(field.getValue()!=null&&!"".equals(field.getValue().toString())){
									temp=field.getValue().toString();
								}
								for(String key:map.keySet()){
									if( map.get(key)!=null&&!"".equals(map.get(key).toString())){
										//System.out.println(temp+":"+"\\$\\{"+entity.getCode()+"."+key+"\\}"+":"+map.get(key).toString());
										temp=temp.replace("${"+entity.getCode()+"."+key+"}", map.get(key).toString());
									}
								}
								field.setValue(temp);
							}
						}
					}
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}


	public boolean move(String code, String id1,String id2, String type) {
		DefaultEntity entity=getEntity(code);
		IModel m1=getById(entity,id1);
		IModel m2=getById(entity,id2);
		sortModel(entity,m1,m2,type);
		save(entity);
		return true;
	}
	private boolean sortModel(IModel entity,IModel source,IModel target,String type){
		List<Object> list=AnnoUtils.getField(entity.getClass(), TreeNode.class, entity);
		for(Object obj:list){
			if(obj instanceof IModel){
				if(obj instanceof INode){
					INode node=(INode)obj;
					if(node.getList().contains(target)){
						sort(node.getList(),source,target,type);
						return true;
					}
					for(Object o:node.getList()){
						if(sortModel((IModel)o,source,target,type)) return true;
					}
				}else{
					sortModel((IModel)obj,source,target,type);
				}
			}
		}
		return false;
	}
	
	private void sort(List list, IModel source,IModel target1 , String type) {
		//int index=list.indexOf(source);
		int index2=list.indexOf(target1);
		int target=index2;//"before".equals(type)?index2:index2-1;
		if(target<0||target>=list.size())return;
		list.remove(source);
		list.add(target, source);
	}

	public boolean copyEntity(String code, String ids) {
		COPY_ENTITY_BEAN_CACHE= new CopyBean(code,ids);
		return true;
	}

	public boolean pasteEntity(String code, String id) {
		DefaultEntity targetentity=getEntity(code);
		DefaultEntity sourceEntity=getEntity(COPY_ENTITY_BEAN_CACHE.getCode());
		for(String sourceId:COPY_ENTITY_BEAN_CACHE.getList()){
			IModel model=this.getById(sourceEntity, sourceId);
			IModel newModel=(IModel)clone(model);
			reset(newModel);
			this.addModel(targetentity, id,newModel);
		}
		return true;
	}
	public void reset(IModel model) {
		model.setId(Utils.getRandomString(IModel.ID_LEN));
		if(model instanceof INode){
			INode n=(INode)model;
			List<Object> l=n.getList();
			for(Object obj:l){
				if(obj instanceof IModel){
					reset((IModel)obj);
				}
			}
		}
		List<Object> list=AnnoUtils.getField(model.getClass(), TreeNode.class, model);
		for(Object obj:list){
			if(obj instanceof IModel){
				reset((IModel)obj);
			}
		}
	}

	public  String getRuleDataAuth(DefaultEntity se,UserBean userBean){
		String sql="";
		DefaultConfig rule=se.getConfigs().getList().get(0);

		String ruleJSON=rule.getDataAuth();
		if(rule!=null&&Utils.isNotNull(ruleJSON)){
			//System.out.println(ruleJSON);
			if("[{\"type\":\"op\",\"op\":\"and\"}]".equals(ruleJSON))return "";
			List<Map<String,Object>> list=((List<Map<String,Object>>)JSON.parse(ruleJSON));
			for(Map<String,Object> map:list) {
				sql+=ruleMapToSql(map,userBean);
			}
			
			//System.out.println(sql);
			sql=formatRule(sql,userBean);
			sql=" and "+sql.replaceAll("  ", " ");
		}
		//System.out.println("["+sql+"]");
		return sql;
	}
	private static String formatRule(String sql,UserBean userBean){
		if(userBean==null)return sql;
		//sql=sql.replaceAll("\\{authOrg\\}", "(select org_id from tlingx_roleorg where role_id in(select role_id from tlingx_userrole where user_id='"+userBean.getId()+"'))");
		//sql=sql.replaceAll("\\{authRole\\}", "(select refrole_id from tlingx_rolerole where role_id in(select role_id from tlingx_userrole where user_id='"+userBean.getId()+"'))");
		//sql=sql.replaceAll("\\{authFunc\\}", "(select func_id from tlingx_rolefunc where role_id in(select role_id from tlingx_userrole where user_id='"+userBean.getId()+"'))");
		//sql=sql.replaceAll("\\{currentDevApp\\}", "(select id from tlingx_app where status=1)");
		//sql=sql.replaceAll("\\{authMenu\\}", "(select menu_id from tlingx_rolemenu where role_id in(select role_id from tlingx_userrole where user_id='"+userBean.getId()+"'))");
		
		sql=sql.replaceAll("\\{currentOrg\\}","(select org_id from tlingx_userorg where user_id='"+userBean.getId()+"')");
		//sql=sql.replaceAll("\\{currentApp\\}","'"+userBean.getApp().getId()+"'");
		sql=sql.replaceAll("\\{currentUser\\}","'"+userBean.getId()+"'");
		sql=sql.replaceAll("\\{currentRole\\}","(select role_id from tlingx_user_role where user_id='"+userBean.getId()+"')");
		
		sql=sql.replaceAll("\\{currentUserOrg\\}","'"+userBean.getOrgId()+"'");
		sql=sql.replaceAll("\\{currentRoleOrg\\}","(select org_id from tlingx_user_role where user_id='"+userBean.getId()+"')");
		
//		sql=sql.replaceAll("\\{authOrg2\\}","'"+userBean.getRegexp().getAuthOrg()+"'");
//		sql=sql.replaceAll("\\{authRole2\\}","'"+userBean.getRegexp().getAuthRole()+"'");
//		sql=sql.replaceAll("\\{currentOrg2\\}","'"+userBean.getRegexp().getCurrentOrg()+"'");
//		sql=sql.replaceAll("\\{currentRole2\\}","'"+userBean.getRegexp().getCurrentRole()+"'");
//		sql=sql.replaceAll("\\{subOrg2\\}","'"+userBean.getRegexp().getSubOrg()+"'");
//		sql=sql.replaceAll("\\{appOrg2\\}","'"+userBean.getRegexp().getAppOrg()+"'");
//		sql=sql.replaceAll("\\{roleOrg2\\}","'"+userBean.getRegexp().getRoleOrg()+"'");
//		
//		sql=sql.replaceAll("\\{subOrg\\}","('"+userBean.getRegexp().getSubOrg().replace("|", "','")+"')");
//		sql=sql.replaceAll("\\{appOrg\\}","('"+userBean.getRegexp().getAppOrg().replace("|", "','")+"')");
//		sql=sql.replaceAll("\\{roleOrg\\}","('"+userBean.getRegexp().getRoleOrg().replace("|", "','")+"')");
//		
		return sql;
	}
	private  String ruleMapToSql(Map<String,Object> map,UserBean userBean){
		StringBuilder sb=new StringBuilder();
		if(map==null||map.get("type")==null)return " 1=1 ";
		if(map.get("type").toString().equals("group")){
			List<Map<String,Object>> list=(List<Map<String,Object>>)map.get("group");
			sb.append(" ( ");
			String op="";
			for(Map<String,Object> m:list){
				if(m.get("type").toString().equals("op")){
					op=m.get("op").toString();
				}
			}
			for(Map<String,Object> m:list){
				if(m.get("type").toString().equals("op"))continue;
				sb.append(ruleMapToSql(m,userBean)).append("  ").append(op);
			}
			sb.delete(sb.length()-3, sb.length());
			sb.append(" ) ");
		}else if(map.get("type").toString().equals("condi")){
			String right=map.get("right").toString();
			right=formatRight(right,userBean);//对右边的参数特别处理，如：tuserorg.userid
			sb.append(" ").append(formatLeft(map.get("left").toString())).append(" ").append(map.get("op")).append(" ").append(right).append(" ");
		}else if(map.get("type").toString().equals("op")){
			sb.append(" ").append(map.get("op")).append(" ");
		}
		return sb.toString().replaceAll("  ", " ");
	}

	private String formatLeft(String left){
		if(left.length()==36&&left.indexOf("-")>0){
			left="'"+left+"'";
		}
		return left;
	}
	private  String formatRight(String right,UserBean userBean){
		int len=right.indexOf(".");
		if(len==-1)return right;
		else{
			//属于对象引用
			DefaultEntity entity=this.getEntity(right.substring(0,len));
			String subRule=getRuleDataAuth(entity,userBean);//and  ( ( org_id in (select org_id from tuserorg where userid=198) ) ) 
			
			StringBuilder sb=new StringBuilder();
			sb.append("( select ");
			sb.append(right.substring(len+1)).append(" from ");
			sb.append(entity.getTableName()).append(" where 1=1 ");
			sb.append(subRule);
			sb.append(" )");
			
			return sb.toString();
		}
	}
	public String getCode(){
		try {
			InetAddress ia = InetAddress.getLocalHost();			byte[] m = NetworkInterface.getByInetAddress(ia).getHardwareAddress();			StringBuffer sb = new StringBuffer("");			for(int i=0; i<m.length; i++) {				if(i!=0) {					sb.append("-");				}								int temp = m[i]&0xff;				String str = Integer.toHexString(temp);				if(str.length()==1) {					sb.append("0"+str);				}else {					sb.append(str);				}			}			return Utils.md5(sb.toString()+"5").substring(2);
		} catch (Exception e) {
			String c=getLinuxMACAddress() ;
			if(Utils.isNull(c)){
				c=getUnixMACAddress();
			}
			if(Utils.isNull(c)){
				c="none;";
			}
			return  Utils.md5(c+"5").substring(2);
		}
	}
	private static String getLinuxMACAddress() {  
        String mac = null;  
        BufferedReader bufferedReader = null;  
        Process process = null;  
        try {  
            // linux下的命令，一般取eth0作为本地主网卡 显示信息中包含有mac地址信息  
            process = Runtime.getRuntime().exec("ifconfig eth0");  
            bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));  
            String line = null;  
            int index = -1;  
            while ((line = bufferedReader.readLine()) != null) {  
                index = line.toLowerCase().indexOf("硬件地址");  
                if (index != -1) {  
                    // 取出mac地址并去除2边空格  
                    mac = line.substring(index + 4).trim();  
                    break;  
                }  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (bufferedReader != null) {  
                    bufferedReader.close();  
                }  
            } catch (IOException e1) {  
                e1.printStackTrace();  
            }  
            bufferedReader = null;  
            process = null;  
        }  
        return mac;  
    }  
      
  
	private static String getUnixMACAddress() {  
        String mac = null;  
        BufferedReader bufferedReader = null;  
        Process process = null;  
        try {  
            // Unix下的命令，一般取eth0作为本地主网卡 显示信息中包含有mac地址信息  
            process = Runtime.getRuntime().exec("ifconfig eth0");  
            bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));  
            String line = null;  
            int index = -1;  
            while ((line = bufferedReader.readLine()) != null) {  
                // 寻找标示字符串[hwaddr]  
                index = line.toLowerCase().indexOf("hwaddr");  
                if (index != -1) {  
                    // 取出mac地址并去除2边空格  
                    mac = line.substring(index + "hwaddr".length() + 1).trim();  
                    break;  
                }  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (bufferedReader != null) {  
                    bufferedReader.close();  
                }  
            } catch (IOException e1) {  
                e1.printStackTrace();  
            }  
            bufferedReader = null;  
            process = null;  
        }  
  
        return mac;  
    }  
	public static CopyBean COPY_ENTITY_BEAN_CACHE=null;
	static class CopyBean{
		private String code;
		private List<String> list;
		public CopyBean(String code,String ids){
			this.code=code;
			this.list=new ArrayList<String>();
			String array[]=ids.split(",");
			for(String s:array){
				if(s!=null)
				this.list.add(s);
			}
		}
		public String getCode() {
			return code;
		}
		public List<String> getList() {
			return list;
		}
	}
	
}
